package com.dev.shiro.config;

import com.dev.shiro.entity.Login;
import com.dev.shiro.shiro.MySessionDao;
import com.dev.shiro.shiro.MySessionListener;
import com.dev.shiro.shiro.UserRealm;
import org.apache.shiro.mgt.SecurityManager;
import org.apache.shiro.session.mgt.SessionManager;
import org.apache.shiro.session.mgt.eis.JavaUuidSessionIdGenerator;
import org.apache.shiro.spring.LifecycleBeanPostProcessor;
import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.filter.authc.LogoutFilter;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.apache.shiro.web.servlet.SimpleCookie;
import org.apache.shiro.web.session.mgt.DefaultWebSessionManager;
import org.crazycake.shiro.RedisCacheManager;
import org.crazycake.shiro.RedisManager;
import org.crazycake.shiro.RedisSessionDAO;
import org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.DependsOn;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;

import javax.annotation.Resource;
import javax.servlet.Filter;
import java.util.*;

/**
 * @ClassName : ShiroConfig  //类名
 * @Description : shiro配置  //描述
 * @Author : admin //作者
 * @Date: 2020-12-07 14:51  //时间
 */
@Configuration
public class ShiroConfig {

    @Value("${shiro.user.loginUrl}")
    private String loginUrl;
    @Value("${shiro.user.indexUrl}")
    private String indexUrl;
    @Value("${shiro.user.unauthorizedUrl}")
    private String unauthorizedUrl;
    @Value("${shiro.redis.host}")
    private String host;
    @Value("${shiro.redis.timeout}")
    private Integer timeout;

    @Bean
    public SecurityManager securityManager()
    {
        DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
        securityManager.setRealm(userRealm());
        securityManager.setCacheManager(redisCacheManager());
        securityManager.setSessionManager(defaultWebSessionManager());
        return securityManager;
    }

    @Bean
    public JavaUuidSessionIdGenerator javaUuidSessionIdGenerator(){
        return new JavaUuidSessionIdGenerator();
    }

    @Bean
    public RedisManager redisManager() {
        RedisManager redisManager = new RedisManager();
        redisManager.setHost(host);
        redisManager.setTimeout(timeout);
        return redisManager;
    }

    @Bean
    public RedisCacheManager redisCacheManager(){
        RedisCacheManager redisCacheManager = new RedisCacheManager();
        redisCacheManager.setRedisManager(redisManager());
        return redisCacheManager;
    }

    @Bean
    public RedisSessionDAO redisSessionDAO(){
        RedisSessionDAO redisSessionDAO = new RedisSessionDAO();
        redisSessionDAO.setRedisManager(redisManager());
        redisSessionDAO.setSessionIdGenerator(javaUuidSessionIdGenerator());
        redisSessionDAO.setExpire(1800);
        return redisSessionDAO;
    }

    @Bean
    public SimpleCookie simpleCookie(){
        SimpleCookie simpleCookie = new SimpleCookie();
        simpleCookie.setPath("/");
        simpleCookie.setName("JSESSIONID-SHARE");
        simpleCookie.setHttpOnly(true);
        return simpleCookie;
    }

    @Bean
    public MySessionListener sessionListener(){
        return new MySessionListener();
    }

    @Bean
    public DefaultWebSessionManager defaultWebSessionManager(){
        DefaultWebSessionManager defaultWebSessionManager = new DefaultWebSessionManager();
        //sessionDao
        defaultWebSessionManager.setSessionDAO(redisSessionDAO());
        //JSESSIONID
        defaultWebSessionManager.setSessionIdCookie(simpleCookie());
        defaultWebSessionManager.setSessionListeners(new ArrayList<>(List.of(sessionListener())));
        //超时
        defaultWebSessionManager.setGlobalSessionTimeout(1800);
        //删除无效session
        defaultWebSessionManager.setDeleteInvalidSessions(true);
        //解决地址栏JSESSIONID问题
        defaultWebSessionManager.setSessionIdUrlRewritingEnabled(false);
        defaultWebSessionManager.setSessionValidationInterval(5000);
        defaultWebSessionManager.setSessionValidationSchedulerEnabled(true);
        return defaultWebSessionManager;
    }

    //@Bean
    //public DefaultWebSecurityManager securityManager(){
    //    DefaultWebSecurityManager defaultWebSecurityManager = new DefaultWebSecurityManager();
    //    defaultWebSecurityManager.setSessionManager(defaultWebSessionManager());
    //    defaultWebSecurityManager.setRealm(userRealm());
    //    defaultWebSecurityManager.setCacheManager(redisCacheManager());
    //    return defaultWebSecurityManager;
    //}

    /**
     * 自定义 userRealm
     */
    @Bean
    public UserRealm userRealm()
    {
        return new UserRealm();
    }

    /**
     * 退出过滤器
     */
    public LogoutFilter logoutFilter()
    {
        LogoutFilter logoutFilter = new LogoutFilter();
        logoutFilter.setRedirectUrl(loginUrl);
        return logoutFilter;
    }

    /**
     * Shiro过滤器配置
     */
    @Bean
    public ShiroFilterFactoryBean shiroFilterFactoryBean()
    {
        ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
        // Shiro的核心安全接口,这个属性是必须的
        shiroFilterFactoryBean.setSecurityManager(securityManager());
        // 身份认证失败，则跳转到登录页面的配置
        shiroFilterFactoryBean.setLoginUrl(loginUrl);
        shiroFilterFactoryBean.setSuccessUrl(indexUrl);
        // 权限认证失败，则跳转到指定页面
        shiroFilterFactoryBean.setUnauthorizedUrl(unauthorizedUrl);
        // Shiro连接约束配置，即过滤链的定义
        LinkedHashMap<String, String> filterChainDefinitionMap = new LinkedHashMap<>();
        // “/system” 开头的需要身份认证
        filterChainDefinitionMap.put("/system*", "authc");
        // “/mobile” 开头的需要角色认证，是“mobile”才允许
        filterChainDefinitionMap.put("/mobile*", "roles[mobile]");
        // “/platform” 开头的需要权限认证，是“platform:view”才允许
        filterChainDefinitionMap.put("/platform*", "perms[\"platform:view\"]");
        // 不需要拦截的访问
        filterChainDefinitionMap.put("/login", "anon");

        Map<String, Filter> filters = new LinkedHashMap<String, Filter>();
        // 注销成功，则跳转到指定页面
        filters.put("logout", logoutFilter());
        shiroFilterFactoryBean.setFilters(filters);

        // 所有请求需要认证
        filterChainDefinitionMap.put("/**", "user");
        shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);

        return shiroFilterFactoryBean;
    }

    //@Bean
    //@DependsOn("lifecycleBeanPostProcessor")
    //public DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator(){
    //    DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator = new DefaultAdvisorAutoProxyCreator();
    //    defaultAdvisorAutoProxyCreator.setProxyTargetClass(true);
    //    return defaultAdvisorAutoProxyCreator;
    //}
    //
    //@Bean
    //public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor() {
    //    AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor = new AuthorizationAttributeSourceAdvisor();
    //    authorizationAttributeSourceAdvisor.setSecurityManager(securityManager());
    //    return authorizationAttributeSourceAdvisor;
    //}

    //@Bean
    //public LifecycleBeanPostProcessor lifecycleBeanPostProcessor(){
    //    return new LifecycleBeanPostProcessor();
    //}
}
